#include <SFML/Graphics.hpp>
#include <math.h>
using namespace sf;

const int num = 8; // 检查点
int points[num][2] = {
	300, 610,
	1270, 430,
	1380, 2380,
	1900, 2460,
	1970, 1700,
	2550, 1680,
	2560, 3150,
	500, 3300};

struct Car
{
	float x, y, speed, angle;
	int n;

	Car()
	{
		speed = 2;
		angle = 0;
		n = 0;
	}

	void move()
	{
		x += sin(angle) * speed;
		y -= cos(angle) * speed;
	}

	void findTarget() // 检查点
	{
		float tx = points[n][0];
		float ty = points[n][1];
		float beta = angle - atan2(tx - x, -ty + y);
		if (sin(beta) < 0)
			angle += 0.005 * speed;
		else
			angle -= 0.005 * speed;
		if ((x - tx) * (x - tx) + (y - ty) * (y - ty) < 25 * 25)
			n = (n + 1) % num;
	}
};

// 碰撞
bool isCollide(Sprite &sp1, Sprite &sp2)
{
	// getGlobalBounds 返回 精灵所在的矩形
	// intersects 检查两个矩形之间的交点
	return sp1.getGlobalBounds().intersects(sp2.getGlobalBounds());
}

bool loadfile(Texture &Tex1,Texture &Tex2,std::string path)
{
	Tex1.loadFromFile(path + "background.png");
	return Tex2.loadFromFile(path + "car.png");
}

int main()
{
	RenderWindow app(VideoMode(640, 480), "Car Racing!");
	app.setFramerateLimit(60);
	Texture t1, t2;
	if(!loadfile(t1,t2,"../images/"))
		if(!loadfile(t1,t2,"images/"))
			return 0;

	/* 启用或禁用平滑滤镜 激活滤镜后，纹理看起来更平滑，因此像素不太明显。但是，如果您希望纹理看起来与其源文件完全相同，则应将其禁用。默认情况下，平滑滤镜处于禁用状态。 */
	t1.setSmooth(true);
	t2.setSmooth(true);

	Sprite back(t1), scar(t2);
	/* 缩放对象 此函数将对象的当前缩放比例相乘， */
	back.scale(2, 2);
	scar.setOrigin(22, 23); // 中心

	float R = 22; // 碰撞半径
	const int N = 5;
	Car car[N];
	for (int i = 0; i < N; i++)
	{
		car[i].x = 300 + i * 50;
		car[i].y = 1700 + i * 80;
		car[i].speed = 7 + i;
	}

	float speed = 0, angle = 0; // 速度
	float maxSpeed = 10.0;
	float acc = 0.15, dec = 0.25; // 加速度 最短升速时间 最短降速时间
	float turnSpeed = 0.06;

	int offsetX = 0, offsetY = 0;

	while (app.isOpen())
	{
		Event e;
		while (app.pollEvent(e))
		{
			if (e.type == Event::Closed)
				app.close();
			if (Keyboard::isKeyPressed(Keyboard::Escape))
				app.close();
		}

		bool Up = 0, Right = 0, Down = 0, Left = 0; // 状态 640, 480
		if ((Keyboard::isKeyPressed(Keyboard::Up) || Keyboard::isKeyPressed(Keyboard::W)))
			Up = 1;
		if (Keyboard::isKeyPressed(Keyboard::Right) || Keyboard::isKeyPressed(Keyboard::D))
			Right = 1;
		if (Keyboard::isKeyPressed(Keyboard::Down) || Keyboard::isKeyPressed(Keyboard::S))
			Down = 1;
		if (Keyboard::isKeyPressed(Keyboard::Left) || Keyboard::isKeyPressed(Keyboard::A))
			Left = 1;

		////////// car移动 //////////
		int nowCX = car[0].x;
		int nowCY = car[0].y;
		if (Up && speed < maxSpeed) // 加速
			if (speed < 0)
				speed += dec;
			else
				speed += acc;

		if (Down && speed > -maxSpeed) // 减速
			if (speed > 0)
				speed -= dec;
			else
				speed -= acc;

		if (!Up && !Down) // 没有按
			if (speed - dec > 0)
				speed -= dec;
			else if (speed + dec < 0)
				speed += dec;
			else
				speed = 0;
		// 转向
		if (Right && speed != 0)
			angle += turnSpeed * speed / maxSpeed;
		if (Left && speed != 0)
			angle -= turnSpeed * speed / maxSpeed;

		// 赋值
		car[0].speed = speed;
		car[0].angle = angle;

		for (int i = 0; i < N; i++)
			car[i].move();
		for (int i = 1; i < N; i++)
			car[i].findTarget();

		// 碰撞
		for (int i = 0; i < N; i++)
			for (int j = 0; j < N; j++)
			{
				int dx = 0, dy = 0;
				while (dx * dx + dy * dy < 4 * R * R) //
				{
					car[i].x += dx / 10.0;
					car[i].y += dy / 10.0;
					car[j].x -= dx / 10.0;
					car[j].y -= dy / 10.0;
					dx = car[i].x - car[j].x;
					dy = car[i].y - car[j].y;
					if (!dx && !dy)
						break;
				}
			}

		// 地图边界时 不移动
		int nowoffsetX = offsetX;
		int nowoffsetY = offsetY;
		if (car[0].x > 320)
		{
			offsetX = car[0].x - 320;
			if (offsetX > 1440 * 2 - 640)
				offsetX = nowoffsetX;
		}
		if (car[0].y > 240)
		{
			offsetY = car[0].y - 240;
			if (offsetY >= 1820 * 2 - 480)
				offsetY = nowoffsetY;
		}
		scar.setPosition(car[0].x - offsetX, car[0].y - offsetY); // 地图 与小车同时移动，位移抵消

		if (!isCollide(scar, back))
		{
			car[0].x = nowCX;
			car[0].y = nowCY;
			// offsetX = nowoffsetX;
			// offsetY = nowoffsetY;
		}
		/////// draw ///////
		app.clear(Color::White);
		back.setPosition(-offsetX, -offsetY); // 地图移动，与小车反向
		app.draw(back);
		Color color[10] = {Color::Red, Color::Blue, Color::Yellow, Color::Magenta, Color::White};

		for (int i = 0; i < N; i++)
		{
			scar.setPosition(car[i].x - offsetX, car[i].y - offsetY); // 地图 与小车同时移动，位移抵消
			/* 设置对象的方向 此函数完全覆盖之前的旋转。请参阅旋转功能以改为基于上一个旋转添加角度。可转换对象的默认旋转为 0。 */
			scar.setRotation(car[i].angle * 180 / 3.1415926);
			scar.setColor(color[i]);
			app.draw(scar);
		}

		app.display();
	}

	return 0;
}
